//File   : wav_parser.c  
//Author : Loon <sepnic@gmail.com>  
  
#include <assert.h>  
#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <fcntl.h>  
  
#include "wav_parser.h"  
  
#define WAV_PRINT_MSG  
  
char *WAV_P_FmtString(uint16_t fmt)  
{  
    switch (fmt) {  
    case WAV_FMT_PCM:  
        return "PCM";  
        break;  
    case WAV_FMT_IEEE_FLOAT:  
        return "IEEE FLOAT";  
        break;  
    case WAV_FMT_DOLBY_AC3_SPDIF:  
        return "DOLBY AC3 SPDIF";  
        break;  
    case WAV_FMT_EXTENSIBLE:  
        return "EXTENSIBLE";  
        break;  
    default:  
        break;  
    }  
  
    return "NON Support Fmt";  
}  
  
void WAV_P_PrintHeader(WAVContainer_t *container)  
{  
    printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");  
    printf("\n");  
      
    printf("File Magic:         [%c%c%c%c]\n",   
        (char)(container->header.magic),   
        (char)(container->header.magic>>8),   
        (char)(container->header.magic>>16),   
        (char)(container->header.magic>>24));  
    printf("File Length:        [%d]\n", container->header.length);  
    printf("File Type:          [%c%c%c%c]\n",  
        (char)(container->header.type),   
        (char)(container->header.type>>8),   
        (char)(container->header.type>>16),   
        (char)(container->header.type>>24));  
          
    printf("\n");  
  
    printf("Fmt Magic:          [%c%c%c%c]\n",  
        (char)(container->format.magic),   
        (char)(container->format.magic>>8),   
        (char)(container->format.magic>>16),   
        (char)(container->format.magic>>24));  
    printf("Fmt Size:           [%d]\n", container->format.fmt_size);  
    printf("Fmt Format:         [%s]\n", WAV_P_FmtString(container->format.format));  
    printf("Fmt Channels:       [%d]\n", container->format.channels);  
    printf("Fmt Sample_rate:    [%d](HZ)\n", container->format.sample_rate);  
    printf("Fmt Bytes_p_second: [%d]\n", container->format.bytes_p_second);  
    printf("Fmt Blocks_align:   [%d]\n", container->format.blocks_align);  
    printf("Fmt Sample_length:  [%d]\n", container->format.sample_length);  
      
    printf("\n");  
  
    printf("Chunk Type:         [%c%c%c%c]\n",  
        (char)(container->chunk.type),   
        (char)(container->chunk.type>>8),   
        (char)(container->chunk.type>>16),   
        (char)(container->chunk.type>>24));  
    printf("Chunk Length:       [%d]\n", container->chunk.length);  
      
    printf("\n");  
    printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");  
}  
  
int WAV_P_CheckValid(WAVContainer_t *container)  
{  
    if (container->header.magic != WAV_RIFF ||  
        container->header.type != WAV_WAVE ||  
        container->format.magic != WAV_FMT ||  
        container->format.fmt_size != LE_INT(16) ||  
        (container->format.channels != LE_SHORT(1) && container->format.channels != LE_SHORT(2)) ||  
        container->chunk.type != WAV_DATA) {  
          
        fprintf(stderr, "non standard wav file.\n");  
        return -1;  
    }  
  
    return 0;  
}  
  
int WAV_ReadHeader(int fd, WAVContainer_t *container)  
{  
    assert((fd >=0) && container);  
  
    if (read(fd, &container->header, sizeof(container->header)) != sizeof(container->header) ||   
        read(fd, &container->format, sizeof(container->format)) != sizeof(container->format) ||  
        read(fd, &container->chunk, sizeof(container->chunk)) != sizeof(container->chunk)) {  
  
        fprintf(stderr, "Error WAV_ReadHeader\n");  
        return -1;  
    }  
  
    if (WAV_P_CheckValid(container) < 0)  
        return -1;  
  
#ifdef WAV_PRINT_MSG  
    WAV_P_PrintHeader(container);  
#endif  
  
    return 0;  
}  
  
int WAV_WriteHeader(int fd, WAVContainer_t *container)  
{  
    assert((fd >=0) && container);  
      
    if (WAV_P_CheckValid(container) < 0)  
        return -1;  
  
    if (write(fd, &container->header, sizeof(container->header)) != sizeof(container->header) ||   
        write(fd, &container->format, sizeof(container->format)) != sizeof(container->format) ||  
        write(fd, &container->chunk, sizeof(container->chunk)) != sizeof(container->chunk)) {  
          
        fprintf(stderr, "Error WAV_WriteHeader\n");  
        return -1;  
    }  
  
#ifdef WAV_PRINT_MSG  
    WAV_P_PrintHeader(container);  
#endif  
  
    return 0;  
}  
